package com.dingding.service.share.dao.impl;

import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.dingding.common.core.base.daox.IBaseDaoX;
import com.dingding.common.core.base.daox.ICriteriaBaseDao;
import com.dingding.common.core.base.daox.ISQLBaseDao;
import com.dingding.common.core.beans.Activity;
import com.dingding.common.core.beans.ActivityInfoBanner;
import com.dingding.common.core.beans.Phonevalidate;
import com.dingding.common.core.beans.UserLogin;
import com.dingding.common.core.beans.share.ActivityGift;
import com.dingding.common.core.beans.share.ActivityRefGift;
import com.dingding.common.core.beans.share.ActivityShare;
import com.dingding.common.core.beans.share.ActivityShareRefGift;
import com.dingding.common.core.beans.share.ActivityShareRegRecord;
import com.dingding.common.core.config.Constants;
import com.dingding.common.core.exception.bussiness.BizExpEnum;
import com.dingding.common.core.exception.bussiness.BussinessException;
import com.dingding.common.core.exception.server.ServerException;
import com.dingding.common.core.exception.server.ServerExpEnum;
import com.dingding.common.core.util.DateUtils;
import com.dingding.common.core.util.JSONUtil;
import com.dingding.common.core.util.ToolUtil;
import com.dingding.facade.queue.dto.msg.MessageRequestsDTO;
import com.dingding.facade.queue.facade.IQueueFacade;
import com.dingding.facde.activity.dto.commonactivity.ActivityDetail;
import com.dingding.facde.activity.dto.commonactivity.GiftInfo;
import com.dingding.service.share.dao.IActivityShareDao;
import com.dingding.service.share.sql.ShareActivitySql;

/**
 * @Description:活动分享的dao
 * @author fengshuonan
 * @date 2016年9月5日 下午5:40:21
 * @version 叮叮搭车
 * @since 2.4
 */
@Component("activityShareDao")
public class ActivityShareDaoImpl implements IActivityShareDao{
	
	private Logger log = Logger.getLogger(this.getClass());

	@Resource(name = "criteriaBaseDao")
	private ICriteriaBaseDao criteriaBaseDao;
	
	@Resource(name = "queueFacade")
	private IQueueFacade queueFacade;
	
	@Resource(name = "baseDaoX")
	private IBaseDaoX baseDaoX;
	
	@Resource(name = "SQLBaseDao")
	private ISQLBaseDao SQLBaseDao;
	
	/**
	 * @Description:获取用户的分享记录
	 * @param userId 用户id
	 * @param activityId 活动id
	 * @author fengshuonan
	 * @return ActivityShare 生成活动分享记录
	 * @since 2.4
	 */
	@Override
	@Transactional(readOnly = true)
	public ActivityShare getUserActivityShare(String userId, String activityId) {
		Criterion criterion = Restrictions.and(
				Restrictions.eq("userId", userId),Restrictions.eq("acId", activityId));
		ActivityShare activityShare = criteriaBaseDao.queryCriteriaListUnique(ActivityShare.class, criterion);
		if(activityShare == null){
			return null;
		}else{
			return activityShare;
		}
	}

	/**
	 * @Description:获取某个用户的活动的所选的礼品
	 * @param shareKey 用户活动标识
	 * @author fengshuonan
	 * @return String[] 礼品的集合
	 * @since 2.4
	 */
	@Override
	@Transactional(readOnly = true)
	public String[] getGiftList(String shareKey) {
		
		Criterion criterion = Restrictions.eq("shareKey", shareKey);
		List<ActivityShareRefGift> queryCriteriaList = null;
		try {
			queryCriteriaList = criteriaBaseDao.queryCriteriaList(ActivityShareRefGift.class, criterion);
		} catch (HibernateException e) {
			log.error("获取某个用户所选的礼品集合出现错误！ActivityShareDaoImpl:getGiftList()",e);
		}
		if(queryCriteriaList == null || queryCriteriaList.size() == 0){
			return null;
		}else{
			String[] gifts = new String[queryCriteriaList.size()];
			for(int i=0;i<queryCriteriaList.size();i++){
				gifts[i] = queryCriteriaList.get(i).getGiftId();
			}
			return gifts;
		}
	}
	
	/**
	 * @Description:判断openId是否存在于数据库中
	 * @param openId 微信公众号id
	 * @author fengshuonan
	 * @return boolean true openId存在  false openId不存在
	 * @since 2.4
	 */
	@Override
	@Transactional(readOnly = true)
	public boolean isOpenIdHaveReg(String openId) {
		UserLogin userLogin = this.getUserLoginByOpenId(openId);
		if(userLogin == null){
			return false;
		}else{
			return true;
		}
	}

	/**
	 * @Description: 判断电话是否注册过,
	 * 			如果注册过，返回用户的登录id,如果没注册过就返回null
	 * @param telephone 电话号码
	 * @author fengshuonan
	 * @since 2.4
	 */
	@Override
	@Transactional(readOnly = true)
	public String isUserHaveReg(String telephone) {
		UserLogin login = this.criteriaBaseDao.queryCriteriaListUnique(
				UserLogin.class, Restrictions.eq("userName", telephone));
		if(login != null){
			return login.getUid();
		}else{
			return null;
		}
	}

	/**
	 * @Description:判断手机号是否正确
	 * @author fengshuonan
	 * @since 2.4
	 */
	@Override
	@Transactional(readOnly = true)
	public boolean isMsgCodeTrue(String telephone, String code) {
		Phonevalidate phonevalidate = this.criteriaBaseDao.queryCriteriaListUnique(
				Phonevalidate.class, Restrictions.and(
						Restrictions.eq("phoneNum", telephone),Restrictions.eq("validateNum", code)));
		if(phonevalidate == null){
			return false;
		}else{
			//验证是否已经超时（默认10分钟）
			Date date = phonevalidate.getCreateTime();
			Date nowDate = new Date();
			
			//如果验证码超时
			if(DateUtils.getTwoDateDiff(date, nowDate) >= Constants.TELE_CODE_OVERTIME){
				throw new BussinessException(BizExpEnum.TELE_CODE_OVERTIME);//验证码超时
			}else{
				return true;
			}
		}
	}
	
	/**
	 * @Description:增加活动发起者的邀请次数
	 * @param sharekey activityShare的主键id
	 * @author fengshuonan
	 * @return true 添加成功
	 * @since 2.4
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public void addActAnsInviteNum(String shareKey) {
		ActivityShare share = this.criteriaBaseDao.queryCriteriaListUnique(
				ActivityShare.class,Restrictions.eq("asId", shareKey));
		if(share == null){
			throw new BussinessException(BizExpEnum.NO_USER_ACTIVITYSHARE);//没有该用户的活动分享记录
		}else{
			share.setInviteNum(share.getInviteNum() + 1);	//给该用户的邀请人数+1
			share.setUpdateTime(new Date());				//更新时间
			
			//如果邀请人数够的话设置达标时间,并且让库存数量减一
			int reachNum = this.getActivityReachNum(share.getAcId());
			if(share.getInviteNum() == reachNum){
				share.setFinishTime(new Date()); 			//设置达标时间
				
				//让该活动对应的礼品库存减一
				ActivityShareRefGift actShareGift = this.getActShareGift(shareKey);
				this.reduceGiftNumber(share.getAcId(), actShareGift.getGiftId());
			}
		}
	}

	/**
	 * @Description:获取用户id通过phone
	 * @author fengshuonan
	 * @since 2.4
	 */
	@Override
	@Transactional(readOnly = true)
	public String getUserIdByPhone(String phone) {
		UserLogin ul = this.criteriaBaseDao.queryCriteriaListUnique(
				UserLogin.class,Restrictions.eq("userName", phone));
		if(ul != null){
			return ul.getUid();
		}else{
			throw new BussinessException(BizExpEnum.NO_SUCH_USER_IN_USERLOGIN);
		}
	}

	
	/**
	 * @Description:发送短信验证码
	 * @author fengshuonan
	 * @since 2.4
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public boolean sendPhoneMessage(String phone) {
		
		MessageRequestsDTO msg = new MessageRequestsDTO();
		msg.setTelPhone(phone);
		String code = ToolUtil.generateCellPhoneValNum();
		msg.setMessageContent("您好，您的验证码是：" + code);
		
		//判断是否数据库中有记录
		Criterion criterion = Restrictions.eq("phoneNum", phone);
		Phonevalidate phonevalidate= this.criteriaBaseDao.queryCriteriaListUnique(
				Phonevalidate.class, criterion);
		
		//如果数据库中有记录，说明该手机号发送过验证码
		if(phonevalidate != null){
			Date nowTime = new Date();
			
			//判断上次发送验证码时间，如果小于一分钟就不发送
			if(DateUtils.getTwoDateDiff(nowTime, phonevalidate.getCreateTime()) < 60){
				throw new BussinessException(BizExpEnum.PHONE_CODE_TOO_FAST);//发送手机验证码频率过快
			
			//如果上次放松验证码时间间隔大于一分钟就发送
			}else{
				phonevalidate.setValidateNum(String.valueOf(code));
				phonevalidate.setCreateTime(new Date());
				return this.queueFacade.addMessageToQueue(JSONUtil.toJSONString(msg));
			}
		
		//如果是第一次发送验证码
		}else{
			Phonevalidate newValidate = new Phonevalidate();
			newValidate.setCreateTime(new Date());
			newValidate.setVid(ToolUtil.getUid());
			newValidate.setPhoneNum(phone);
			newValidate.setValidateNum(String.valueOf(code));
			newValidate.setValidateCodeNumber(0);
			this.baseDaoX.save(newValidate);
			return this.queueFacade.addMessageToQueue(JSONUtil.toJSONString(msg));
		}
	}

	/**
	 * @Description:获取某个活动的详情
	 * @author fengshuonan
	 * @since 2.4
	 */
	@Override
	@Transactional(readOnly = true)
	public ActivityDetail getActivityInfo(String activityId) {
		ActivityDetail activityDetail = new ActivityDetail();
		
		//获取顶端图片的显示
		ActivityInfoBanner ainfo = this.criteriaBaseDao.queryCriteriaListUnique(ActivityInfoBanner.class, 
				Restrictions.and(Restrictions.eq("activityId", activityId),Restrictions.eq("snSatatus", 1)));
		if(ainfo == null){
			throw new BussinessException(BizExpEnum.EMPTY_ACTI_BANNER);
		}
		activityDetail.setBannerImage(ainfo.getBannerImageName());
		
		//获取活动详情以及活动时间
		Activity activity = this.baseDaoX.getById(activityId, Activity.class);
		if(activity == null){
			throw new BussinessException(BizExpEnum.EMPTY_ACTI_BANNER);
		}
		activityDetail.setTitle(activity.getPropagandaTitle());
		activityDetail.setStartTime(activity.getCreateTime());
		activityDetail.setEndTime(activity.getEndTime());
		activityDetail.setRule(activity.getPropagandaContent());
		activityDetail.setShareType(new String[]{"1","2"});//暂时固定为微信朋友圈和微信公众号
		return activityDetail;
	}

	/**
	 * @Description:获取某个活动对应的礼品的集合
	 * @author fengshuonan
	 * @since 2.4
	 */
	@Override
	@Transactional(readOnly = true)
	public List<GiftInfo> getActivityGifts(String activityId) {
		String sql = ShareActivitySql.GET_ACTIVITY_GIFTS;
		List<GiftInfo> list = this.SQLBaseDao.listSqlToCustomBean(GiftInfo.class, sql, activityId);
		return list;
	}

	/**
	 * @Description:添加用户的活动分享记录
	 * @author fengshuonan
	 * @since 2.4
	 */
	@Override
	public ActivityShare addUsesActivityShare(String activityId,String userId,String giftId){
		
		//查询是否有这个用户
		UserLogin userlogin = this.baseDaoX.getById(userId, UserLogin.class);
		if(userlogin == null){
			throw new BussinessException(BizExpEnum.NO_SUCH_USER_IN_USERLOGIN);//没有用户，不能发起活动
		}
		
		//查询是否有这个礼品,并且这个礼品是否数量充足
		GiftInfo giftInfo = this.getActivityGiftInfo(activityId,giftId);
		if(giftInfo == null){
			throw new BussinessException(BizExpEnum.NO_THIS_GIFT);
		}else if((giftInfo.getTotalNumber() - giftInfo.getResidualNumber()) <= 0){//礼品发放总数减去已经发送数量
			throw new BussinessException(BizExpEnum.GIFT_NUM_NOT_ENOUGH);
		}
		
		//在活动分享表中添加一条记录
		ActivityShare activityShare = new ActivityShare();
		activityShare.setAsId(UUID.randomUUID().toString());
		activityShare.setJoinTime(new Date());
		activityShare.setAcId(activityId);
		activityShare.setInviteNum(0);
		activityShare.setUserId(userId);
		
		if(this.baseDaoX.save(activityShare) != true){
			throw new ServerException(ServerExpEnum.SERVER_DATABASE_EXCEPTION);
		}
		
		//如果添加成功，则在用户礼品表中添加一条记录
		ActivityShareRefGift activityShareRefGift = new ActivityShareRefGift();
		activityShareRefGift.setUgId(ToolUtil.getUid());
		activityShareRefGift.setAsId(activityShare.getAsId());
		activityShareRefGift.setGiftId(giftId);
		
		if(this.baseDaoX.save(activityShareRefGift) != true){
			throw new ServerException(ServerExpEnum.SERVER_DATABASE_EXCEPTION);
		}
		
		return activityShare;
	}

	/**
	 * @Description:根据活动和礼品id获取，礼品详情信息
	 * @author fengshuonan
	 * @since 2.4
	 */
	@Override
	public GiftInfo getActivityGiftInfo(String activityId, String giftId) {
		String sql = ShareActivitySql.GET_ACTIVITY_GIFT_DETAIL;
		List<GiftInfo> list = this.SQLBaseDao.listSqlToCustomBean(GiftInfo.class, sql, activityId,giftId);
		if(list == null || list.size() == 0){
			return null;
		}else{
			return list.get(0);
		}
	}

	/**
	 * @Description:获取活动邀请达标人数
	 * @author fengshuonan
	 * @since 2.4
	 */
	@Override
	public Integer getActivityReachNum(String activityId) {
		
		Activity activity = this.baseDaoX.getById(activityId, Activity.class);
		
		if(activity == null || activity.getCompleteNumber() == null){
			throw new BussinessException(BizExpEnum.EMPTY_ACTIVITY);
		}
		
		return activity.getCompleteNumber();
	}

	/**
	 * @Description:获取用户活动分享的所选的礼物名称
	 * @param shareKey 用户活动分享表的主键id
	 * @author fengshuonan
	 * @since 2.4
	 */
	@Override
	@Transactional(readOnly = true)
	public ActivityGift getUserActivityGiftName(String shareKey) {
		
		//获取用户所选的礼品的id
		ActivityShareRefGift activityShareRefGift = this.criteriaBaseDao.queryCriteriaListUnique(
				ActivityShareRefGift.class, Restrictions.eq("asId", shareKey));
		
		if(activityShareRefGift == null){
			throw new BussinessException(BizExpEnum.NO_USER_ACT_GIFT);
		}else{
			
			//根据giftId查询到礼品的名称
			ActivityGift activityGift = this.baseDaoX.getById(
					activityShareRefGift.getGiftId(), ActivityGift.class);
			if(activityGift == null){
				throw new BussinessException(BizExpEnum.NO_THIS_GIFT);
			}
			return activityGift;
		}
	}

	/**
	 * @Description:获取某个邀请人数的排名
	 * @author fengshuonan
	 * @return 当前邀请人数的排名
	 * @since 2.4
	 */
	@Override
	public Integer getTheNumSort(String activityId,Integer inviteNum) {
		List<ActivityShare> queryCriteriaList = this.criteriaBaseDao.queryCriteriaList(
				ActivityShare.class, Restrictions.and(
						Restrictions.eq("acId", activityId),Restrictions.gt("inviteNum", inviteNum)));
		
		//如果邀请人数有大于@Param inviteNum的，有n个就是第n+1个排名
		if(queryCriteriaList == null || queryCriteriaList.size() == 0){
			return 1;
		}else{
			return queryCriteriaList.size() + 1;
		}
	}

	/**
	 * @Description:判断当前活动的礼品是否充足
	 * @param shareKey 用户发起分享的标示
	 * @author fengshuonan
	 * @return boolean true 充足  false 不充足
	 * @since 2.4
	 */
	@Override
	public boolean isRestGiftEnough(String activityId, String shareKey) {
		
		//查询这个用户选择的礼品
		ActivityShareRefGift activityShareRefGift = this.criteriaBaseDao.queryCriteriaListUnique(
				ActivityShareRefGift.class, Restrictions.eq("asId", shareKey));
		if(activityShareRefGift == null){
			throw new BussinessException(BizExpEnum.NO_USER_ACT_GIFT);//没有该活动分享记录
		}
		
		//查询这个礼品的剩余数量是否充足
		ActivityRefGift ac_gift = this.getActivityGiftDetail(
				activityId, activityShareRefGift.getGiftId());
		if(ac_gift == null){
			throw new BussinessException(BizExpEnum.NO_ACTIVITY_GIFT);//没有该活动分享记录
		}
		if((ac_gift.getTotalNumber() - ac_gift.getResidualNumber()) > 0){ //总量减去已发放数量大于0
			return true;
		}else{
			return false;
		}
	}

	/**
	 * @Description:减少礼品的库存数量
	 * @param activityId 活动id
	 * @param giftId 礼品id
	 * @author fengshuonan
	 * @since 2.4
	 */
	@Override
	public synchronized void reduceGiftNumber(String activityId, String giftId) {
		ActivityRefGift activityGiftDetail = this.getActivityGiftDetail(activityId, giftId);
		if(activityGiftDetail == null){
			throw new BussinessException(BizExpEnum.NO_ACTIVITY_GIFT);
		}else{
			if(activityGiftDetail.getResidualNumber() == null){
				activityGiftDetail.setResidualNumber(0);
			}else if(activityGiftDetail.getTotalNumber() == null){
				activityGiftDetail.setTotalNumber(0);
			}
			
			//如果剩余数量不够,则减少库存数量失败
			if(activityGiftDetail.getTotalNumber() - activityGiftDetail.getResidualNumber() <= 0){
				throw new BussinessException(BizExpEnum.GIFT_NUM_NOT_ENOUGH);//礼品数量不充足
			}
			activityGiftDetail.setResidualNumber(activityGiftDetail.getResidualNumber() + 1);
			activityGiftDetail.setUpdateTime(new Date());
		}
	}

	/**
	 * @Description:获取用户发起分享所选的礼品
	 * @param shareKey 发起分享的唯一标识
	 * @author fengshuonan
	 * @since 2.4
	 */
	@Override
	public ActivityShareRefGift getActShareGift(String shareKey) {
		ActivityShareRefGift shareRefGift = this.criteriaBaseDao.queryCriteriaListUnique(
				ActivityShareRefGift.class, Restrictions.eq("asId", shareKey));
		if(shareRefGift == null){
			return null;
		}else{
			return shareRefGift;
		}
	}
	
	/**
	 * @Description:通过活动id和礼品id获取活动礼品详情
	 * @author fengshuonan
	 * @return ActivityRefGift
	 * @since 2.4
	 */
	public ActivityRefGift getActivityGiftDetail(String acId,String giftId){
		Criterion criterion = Restrictions.and(Restrictions.eq("acId", acId),
				Restrictions.eq("giftId", giftId));
		ActivityRefGift ac_gift = this.criteriaBaseDao.queryCriteriaListUnique(
				ActivityRefGift.class, criterion);
		if(ac_gift == null){
			return null;
		}else{
			return ac_gift;
		}
	}

	/**
	 * @Description:添加被邀请人的记录
	 * @param shareKey 发起分享人的标示
	 * @param invitedUserId 被邀请人的用户id
	 * @author fengshuonan
	 * @since 2.4
	 */
	@Override
	@Transactional(readOnly = false)
	public void addInviteRecord(String shareKey, String invitedUserId) {
		ActivityShareRegRecord activityShareRegRecord = new ActivityShareRegRecord();
		activityShareRegRecord.setAsrrId(ToolUtil.getUid());
		activityShareRegRecord.setAsId(shareKey);
		activityShareRegRecord.setAsrrStatus(1);   //1:启用   2:不启用
 		activityShareRegRecord.setRegUserId(invitedUserId);
		this.baseDaoX.save(activityShareRegRecord);
	}

	/**
	 * @Description:判断数据库中是否有用户的openId
	 * @author fengshuonan
	 * @return String 如果成功，返回该用户的uid，没有则返回null
	 * @since 2.4
	 */
	@Override
	public String haveOpenId(String openId) {
		if(ToolUtil.isBlank(openId)){
			return null;
		}else{
			UserLogin ul = this.criteriaBaseDao.queryCriteriaListUnique(
					UserLogin.class, Restrictions.eq("weChatId", openId));
			if(ul == null){
				return null;		//数据库中有这个openId的记录
			}else{
				return ul.getUid();	//如果有这条记录就返回这个用户的uid
			}
		}
	}

	/**
	 * @Description:更新用户的openId
	 * @author fengshuonan
	 * @since 2.4
	 */
	@Override
	public void updateOpenId(String userId, String openId) {
		UserLogin login = this.baseDaoX.getById(userId, UserLogin.class);
		if(login == null){
			return ;
		}else{
			login.setWeChatId(openId);
		}
	}

	/**
	 * @Description:获取用户登录信息
	 * @author fengshuonan
	 * @since 2.4
	 */
	@Override
	public UserLogin getUserlogin(String userId) {
		UserLogin userLogin = this.baseDaoX.getById(userId, UserLogin.class);
		if(userLogin == null){
			return null;
		}else{
			return userLogin;
		}
	}

	/**
	 * @Description:根据openId获取用户的登录信息
	 * @author fengshuonan
	 * @since 2.4
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public UserLogin getUserLoginByOpenId(String openId) {
		UserLogin ul = this.criteriaBaseDao.queryCriteriaListUnique(
				UserLogin.class, Restrictions.eq("weChatId", openId));
		if(ul == null){
			return null;
		}else{
			return ul;
		}
	}

	/**
	 * @Description 判断用户是否参加或唐山开城活动
	 * @author fengshuonan
	 * @return boolean true 参加过  false 没有参加
	 */
	@Override
	@Transactional(readOnly = true)
	public boolean haveJoinTangshanKaiCheng(String userId) {
		
		List<ActivityShareRegRecord> queryCriteriaList = this.criteriaBaseDao.queryCriteriaList(
				ActivityShareRegRecord.class, 
				Restrictions.and(Restrictions.eq("regUserId", userId),Restrictions.like("asId", "FXS6C%")));
		
		if(queryCriteriaList == null || queryCriteriaList.size() == 0){
			return false;
		}else{
			return true;
		}
	}
}
